home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
pctecap.arc
/
METHOD2.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-03-15
|
10KB
|
318 lines
PAGE ,132
TITLE Method 2
.286C ; Tell MASM 2.0 about 286 instructions
;--------------------------------------------------------------:
; Sample Program 2 :
; :
; This program switches into Protected Virtual Mode, changes :
; the display attribute to reverse video, and returns to Real :
; Mode to exit to DOS :
; :
; Once entered into a file, do the following: :
; MASM SAMPLE2; :
; LINK SAMPLE2; :
; EXE2BIN SAMPLE2 SAMPLE2.COM :
; DEL SAMPLE2.EXE :
; :
; WARNING: This program will "kill" a PC. It should only :
; be run on an AT. :
;--------------------------------------------------------------:
bios_data_seg SEGMENT at 0040h
ORG 0067h
io_rom_init dw ? ; dword variable in BIOS data segment
io_rom_seg dw ? ; used to store a dword address
bios_data_seg ENDS
descriptor STRUC
seg_limit dw 0 ; segment limit (1-65536 bytes)
base_lo_word dw 0 ; 24 bit physical address
base_hi_byte db 0 ; (0 - (16M-1))
access_rights db 0 ; access rights byte
dw 0 ; reserved_386
descriptor ENDS
cmos_port equ 070h
code_seg_access equ 10011011b ;access rights byte for code seg
data_seg_access equ 10010011b ;access rights byte for data seg
enable_bit20 equ 11011111b ;8042 function code to gate A20
port_a equ 060h ;8042 port A
shut_cmd equ 0FEh ;cmd to 8042: shut down AT
shut_down equ 00Fh ;CMOS shut down byte index
status_port equ 064h ;8042 status port
virtual_enable equ 0001h ;LSB=1: Protected Virtual Mode
SUBTTL Macro Definitions
PAGE
;--------------------------------------------------------------:
; These mnemonics are not supported in MASM 2.0 therefore :
; they are supplied here as MACROS. :
;--------------------------------------------------------------:
lgdt MACRO lgdt1
LOCAL lgdt2,lgdt3
db 00Fh
lgdt2 label byte
mov dx,word ptr lgdt1
lgdt3 label byte
org offset lgdt2
db 001h
org offset lgdt3
ENDM
page
lmsw MACRO lmsw1
LOCAL lmsw2,lmsw3
db 00Fh
lmsw2 label byte
mov si,ax
lmsw3 label byte
org offset lmsw2
db 001h
org offset lmsw3
ENDM
jumpfar MACRO jumpfar1,jumpfar2
db 0EAh
dw (offset jumpfar1)
dw jumpfar2
ENDM
SUBTTL Program entry point and data area
PAGE
cseg SEGMENT para public 'code'
ASSUME cs:cseg
ORG 100h
start: jmp short main
EVEN
gdt LABEL word
gdt_desc EQU (($-gdt)/8)*8 + 0000000000000000b
gdt1 descriptor <gdt_leng,,,data_seg_access,>
cs_code EQU (($-gdt)/8)*8 + 0000000000000000b
gdt2 descriptor <cseg_leng,,,code_seg_access,>
cs_data EQU (($-gdt)/8)*8 + 0000000000000000b
gdt3 descriptor <cseg_leng,,,data_seg_access,>
ss_desc EQU (($-gdt)/8)*8 + 0000000000000000b
gdt4 descriptor <0FFFFh,,,data_seg_access,>
ds_desc equ (($-gdt)/8)*8 + 0000000000000000b
gdt5 descriptor <0FFFFh,,,data_seg_access,>
es_desc equ (($-gdt)/8)*8 + 0000000000000000b
gdt6 descriptor <0FFFFh,,,data_seg_access,>
gdt_leng EQU $-gdt
PAGE
;--------------------------------------------------------------:
; Format of the Segment Selector Component: :
; :
; +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ :
; | INDEX +TI+ RPL + :
; +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ :
; :
; TI = Table Indicator (0=GDT, 1=LDT) :
; RPL = Requested Privelege Level (00 = highest; 11 = Lowest) :
;--------------------------------------------------------------:
; Format of the Global Descriptor Table :
; .-----------+ +---> TI :
; V | |++-> RPL :
; GDT ==> +---------------+ | ||| :
; | GDT_DESC | --+ 0000000000000000b :
; +---------------+ :
; | CS_CODE | 0000000000001000b :
; +---------------+ :
; | CS_DATA | 0000000000010000b :
; +---------------+ :
; | SS_DESC | 0000000000011000b :
; +---------------+ :
; | DS_DESC | 0000000000100000b :
; +---------------+ :
; | ES_DESC | 0000000000101000b :
; +---------------+ :
;--------------------------------------------------------------:
SUBTTL Program Main
PAGE
;--------------------------------------------------------------:
; MAIN :
;--------------------------------------------------------------:
ASSUME ds:cseg
main PROC ;ES=DS=CS
cld ;forward
mov dx,cs ;form 24bit address out of
mov cx,offset gdt ;CS:GDT
call form_24bit_address
mov gdt1.base_lo_word,dx ;DESC now points to gdt
mov gdt1.base_hi_byte,cl
mov dx,cs ;form 24bit address out of
xor cx,cx ; CS:0000
call form_24bit_address
mov gdt2.base_lo_word,dx ;CS_CODE now points to
mov gdt2.base_hi_byte,cl ; CSEG as a code segment
mov gdt3.base_lo_word,dx ;CS_DATA now points to
mov gdt3.base_hi_byte,cl ; CSEG as a data segment
mov dx,ss ;form 24bit address out of
xor cx,cx ;SS:0000
call form_24bit_address
mov gdt4.base_lo_word,dx ;SS_DESC now points to
; stack segment
mov gdt4.base_hi_byte,cl
lgdt gdt ;Load the GDTR
mov ah,enable_bit20 ;gate address bit 20 on
call gate_a20
or al,al ;was the command accepted?
jz m_10 ;go if yes
mov dx,offset gate_failure ;print error msg
mov ah,9 ; and terminate
int 21h
int 20h
gate_failure db "Address line A20 failed to Gate open$"
m_10: cli ;No interrupts
pushf ;Simulate INT by pushing Flags,
push cs ; CS,
mov ax,offset real ; and offset of return address.
push ax
pusha ;Now, set up stack the way BIOS block-
push es ; move logic will expect it.
push ds ;On return, this is the way
; the regs will be.
ASSUME ds:bios_data_seg
mov dx,bios_data_seg ;Place on Stack current SS:SP
mov ds,dx
mov io_rom_seg,ss
mov io_rom_init,sp
mov al,shut_down ;Set shutdown byte to
out cmos_port,al ; shut down code x"09"
jmp short $+2 ;I/O delay
mov al,9
out cmos_port+1,al
mov ax,virtual_enable ;machine status word needed
lmsw ax ; to switch to virtual mode
jumpfar m_20,cs_code ;Must purge prefetch queue
m_20: ASSUME ds:cseg ;IN VIRTUAL MODE ...
mov ax,ss_desc ;stack segment selector
mov ss,ax ;user's ss+sp
; is not a descriptor
mov ax,cs_data
mov ds,ax ;DS = CSEG as data
mov gdt5.base_lo_word,0000h ;use 8000 for COLOR
mov gdt5.base_hi_byte,0Bh
mov gdt6.base_lo_word,0000h
mov gdt6.base_hi_byte,0Bh
mov ax,ds_desc
mov ds,ax
mov ax,es_desc
mov es,ax
mov cx,80*25
xor si,si
xor di,di
m_30: lodsw
mov ah,70h ;attribute reverse video
stosw
loop m_30
mov al,shut_cmd ;shutdown cmd
out status_port,al ;get back into REAL mode
m_40: hlt
jmp short m_40
SUBTTL Gate A20
PAGE
;--------------------------------------------------------------:
; GATE_A20 :
; This routine controls a signal which gates address bit 20. :
; The gate A20 signal is an output of the 8042 slave processor.:
; Address bit 20 should be gated on before entering protected :
; mode. It should be gated off after entering real mode from :
; protected mode. :
; Input: (AH)=0DDh addr bit 20 gated off (A20 always 0) :
; (AH)=0DFh addr bit 20 gated on (286 controls A20) :
; Output: (AL)=0 operation successful. 8042 has accepted cmd :
; (AL)=2 Failure -- 8042 unable to accept command. :
;--------------------------------------------------------------:
gate_a20 PROC
cli ;disable ints while using 8042
call empty_8042 ;insure 8042 input buffer empty
jnz gate_a20_01 ;ret if 8042 unable to accept cmd
mov al,0D1h ;8042 command to write output port
out status_port,al ;output cmd to 8042
call empty_8042 ;wait for 8042 to accept command
jnz gate_a20_01 ;ret if 8042 unable to accept cmd
mov al,ah ;8042 port data
out port_a,al ;output port data to 8042
call empty_8042 ;wait for 8042 to port data
gate_a20_01:
ret
gate_a20 ENDP
;--------------------------------------------------------------:
; EMPTY_8042 :
; This routine waits for the 8042 buffer to empty :
; Input: None :
; Output: (AL)=0 8042 input buffer empty (ZF=1) :
; (AL)=2 Time out, 8042 buffer full (ZF=0) :
;--------------------------------------------------------------:
empty_8042 PROC
push cx ;save CX
sub cx,cx ;CX=0 will be time out value
empty_8042_01:
in al,status_port ;read 8042 status port
and al,00000010b ;test inp. buffer full flag (D1)
loopnz empty_8042_01 ;loop until input buffer empty
; or time out
pop cx ;restore CX
ret
empty_8042 ENDP
SUBTTL form_24bit_address
PAGE
;--------------------------------------------------------------:
; FORM_24BIT_ADDRESS :
; Input: DX has some segment :
; CX has some offset :
; Output: DX has base_lo_word :
; CL has base_hi_byte :
;--------------------------------------------------------------:
form_24bit_address PROC
push ax
;DX == s15 s14 s13 s12 s11 ... s04 s03 s02 s01 s00
rol dx,4
;DX == s11 ... s04 s03 s02 s01 s00 s15 s14 s13 s12
mov ax,dx
;AX == s11 ... s04 s03 s02 s01 s00 s15 s14 s13 s12
and dl,0F0h
;DX == s11 ... s04 s03 s02 s01 s00 0 0 0 0
and ax,0Fh
;AX == 0 ... 0 0 0 0 0 s15 s14 s13 s12
add dx,cx ;form_24bit_address
mov cx,ax ;get base_hi_byte in CL
adc cl,ch ;carry in (CH=0)
pop ax
ret
form_24bit_address ENDP
SUBTTL Real Mode re-entry point.
PAGE
ASSUME ds:cseg ; IN REAL MODE ...
real: sti ; turn the int's on
int 20h ; back to DOS
main ENDP
cseg_leng EQU $
cseg ENDS
END start